package com.rnerp.rfid;

import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import android.support.annotation.Nullable;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.modules.core.DeviceEventManagerModule;

import com.nativec.tools.ModuleManager;
import com.nativec.tools.SerialPortFinder;
import com.rfid.ReaderConnector;
import com.rfid.RFIDReaderHelper;
import com.module.interaction.ReaderHelper;
import com.module.interaction.ModuleConnector;
import com.rfid.rxobserver.RXObserver;
import com.rfid.rxobserver.bean.RXInventoryTag;

public class RfidModule extends ReactContextBaseJavaModule {
    private RXObserver rxObserver;
    private SerialPortFinder mSerialPortFinder;
    private RFIDReaderHelper mReaderHelper;
    private static Byte TAG_INVENTORY_ERROR = 0x31;

    public RfidModule(ReactApplicationContext reactContext) {
        super(reactContext);
    }

    // 这个名字在js端标记这个模块
    @Override
    public String getName() {
        return "RfidModule";
    }

    @ReactMethod
    public void close() {
        ModuleManager.newInstance().setUHFStatus(false);// 模块掉电
    }

    @ReactMethod
    public void open() {
        ModuleManager.newInstance().setUHFStatus(true);// 模块上电
    }

    @ReactMethod
    public void release() {
        ModuleManager.newInstance().release();// 释放模块上电掉电控制设备，退出应用的时候必须调用该方法，(2017/08/28之后的系统版本调用该方法还有掉电的作用
    }

    @ReactMethod
    private void openCom() {
        ModuleConnector connector = new ReaderConnector();// 构建连接器
        connector.connectCom("dev/ttyS4", 115200);// 连接指定串口，返回true表示成功，false失败
        rxObserver = new RXObserver() {
            @Override
            protected void onExeCMDStatus(byte cmd, byte status) {
                // 如果指令没有返回额外数据仅包含命令执行的状态码（例如RFIDReaderHelper中的各种以set开头的设置指令函数，）会回调该方法
                // 如果指令返回数据异常一定会回调该方法 status 为异常码
                // cmd可以用来区分具体是哪条命令的返回，命令参考CMD类文档，status指令执行状态码，参考ERROR类文档
                WritableMap params = Arguments.createMap();
                if (status == TAG_INVENTORY_ERROR) {
                    params.putString("ErrorMsg", "盘存标签出错");
                } else {
                    params.putString("ErrorMsg", status + "");
                }
                sendEvent(getReactApplicationContext(), "onExeCMDStatus", params);
            }

            @Override
            protected void onInventoryTag(RXInventoryTag tag) {
                // 当发送盘存指令的时候该方法将会回调，盘存指令包括RFIDReaderHelper中inventory，realTimeInventory，customizedSessionTargetInventory,fastSwitchAntInventory
                // 等函数以及扣扳机
                WritableMap params = Arguments.createMap();
                params.putString("RfidResult", tag.strEPC);
                sendEvent(getReactApplicationContext(), "onInventoryTag", params);
            }

            @Override
            protected void onInventoryTagEnd(RXInventoryTag.RXInventoryTagEnd tagEnd) {
                // 当一条盘存指令执行结束的时候该方法会回调（fastSwitchAntInventory除外），tagEnd为指令结束时的返回数据，具体各个字段的含义
                // 可以参考文档中RXInventoryTag.RXInventoryTagEnd各个字段的含义
                WritableMap params = Arguments.createMap();
                params.putInt("TagCount", tagEnd.mTagCount);
                params.putInt("TotalRead", tagEnd.mTotalRead);
                sendEvent(getReactApplicationContext(), "onInventoryTagEnd", params);
            };
        };
        try {
            mReaderHelper = RFIDReaderHelper.getDefaultHelper();
            // 注册RXObserver对象到RFIDReaderHelper，只有这样一旦RFID模块有数据返回才会回调RXObserver中的相应方法。
            mReaderHelper.registerObserver(rxObserver);
        } catch (Exception e) {
            // TODO: handle exception

        }

    }

    @ReactMethod
    private void getAllDevices() {
        mSerialPortFinder = new SerialPortFinder();
        String[] entries = mSerialPortFinder.getAllDevices();
        String[] path = mSerialPortFinder.getAllDevicesPath();
        String eString = "";
        String epatString = "";
        for (int i = 0; i < entries.length; i++) {
            eString = entries + entries[i];
        }
        ;
        for (int j = 0; j < path.length; j++) {
            epatString = epatString + path[j];
        }
        ;
        WritableMap params = Arguments.createMap();
        params.putString("DevicesResult", eString);
        params.putString("PathResult", epatString);
        sendEvent(getReactApplicationContext(), "getAllDevices", params);
    }

    @ReactMethod
    private void readRfid() {
        if (mReaderHelper == null) {
            try {
                RFIDReaderHelper mReaderHelper = RFIDReaderHelper.getDefaultHelper();
                mReaderHelper.registerObserver(rxObserver);
            } catch (Exception e) {
                // TODO: handle exception
                WritableMap params = Arguments.createMap();
                params.putString("ErrorMsg", "扫描异常，请确认您是否在手持式数据采集终端操作");
                sendEvent(getReactApplicationContext(), "onExeCMDStatus", params);
            }
        }
        /**
         * inventory：多标签识别 标签数据存入读写器缓存区 realTimeInventory：读写器收到此命令后，进行EPC
         * GEN2多标签识别操作。标签数据不存入读写器缓存区，而是实时上传标签的数据 getInventoryBuffer 缓存区中的标签数据（1.数据无重复
         *  2.命令运行完后缓存中的数据并不丢失 ） getAndRe
         * etInventoryBuffer 无重复数据命令执行后缓存区中的数据全部清空
         */
        try {
            mReaderHelper.realTimeInventory((byte) 0xFF, (byte) 0x01);
            // mReaderHelper.inventory((byte) 0xFF, (byte) 0x01);
        } catch (Exception e) {
            WritableMap params = Arguments.createMap();
            params.putString("ErrorMsg", "扫描异常，请确认您是否在手持式数据采集终端操作");
            sendEvent(getReactApplicationContext(), "onExeCMDStatus", params);
        }

    }

    private void sendEvent(ReactContext reactContext, String eventName, @Nullable WritableMap params) {
        reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, params);
    }
}